/** @file    WoshShopWindow.cpp
 *  @author  Alessandro Polo
 *  @version $Id: WoshShopWindow.cpp 2887 2010-08-11 08:09:41Z alex $
 *  @brief
 * File containing methods for the wosh::application::WoshShopWindow class.
 * The header for this class can be found in WoshShopWindow.h, check that file
 * for class description.
 ****************************************************************************/
/* Copyright (c) 2007-2010, WOSH - Wide Open Smart Home 
 * by Alessandro Polo - OpenSmartHome.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the OpenSmartHome.com WOSH nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY Alessandro Polo ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Alessandro Polo BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ****************************************************************************/
 
 #include "WoshShopWindow.h"
 #include "ui_WoshShopWindow.h"

 #include <QtGui>
 #include <bundles/services/DesktopNotifier/DesktopNotifierBundle.h>

 #include <core/WoshKernel.h>
 #include <core/Request.h>
 #include <core/Response.h>
 #include <core/Fact.h>
 #include <core/Table.h>
 #include <core/MethodsCommon.h>

 #include <core/WoshKernel.h>
 #include <core/DeviceManager.h>
 #include <core/FileSystem.h>
 #include <core/UserManager.h>
 #include <core/BusManager.h>
 #include <core/ThreadManager.h>
 #include <core/BundleManager.h>
 #include <core/NetworkManager.h>

 #include <interfaces/services/CommunicationManager.h>

 #include <framework/security/SecurityAuthenticationOS.h>

 #include <framework/gui/GuiUtilities.h>
 #include <framework/gui/dialogs/GuiDialogs.h>

 #include "FormConfiguration.h"
 #include "FormScreenshoter.h"

 #include <framework/gui/components/WidgetWoshBrowser.h>
 #include <framework/gui/components/FormBusViewer.h>
 #include <framework/gui/components/FormConsole.h>
 #include <framework/gui/components/FormLogViewer.h>

 #include <framework/gui/FormContainer.h>
 #include <framework/gui/widgets/wCore_PropertiesProvider.h>


namespace wosh {
  namespace application {
  
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
WoshShopWindow* WoshShopWindow::instance = NULL;

void showWidget_WoshShopWindow( QWidget* qWidget ) {
	if ( WoshShopWindow::instance == NULL )
		qWidget->show();
	else {
		QMdiSubWindow* subWin = WoshShopWindow::instance->m_ui->mdiArea->addSubWindow(qWidget);
		subWin->show();
	 }
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////// CONSTRUCTORS

WoshShopWindow::WoshShopWindow(QWidget *parent)
	: QMainWindow(parent) {
	this->m_ui = new Ui::WoshShopWindow();
	this->m_ui->setupUi(this);

	this->desktopNotifierBundle = NULL;

	this->formScreenshoter = NULL;
	this->formConfiguration = NULL;
	this->formWoshBrowser = NULL;
	this->formLogViewer = NULL;

	Log.setContext("WoshShopWindow");
	Log.setLevel( LOG_VERBOSE );
	Log.setIndent( 1 );

	this->myUri.setKernelLocal();
	this->myUri.clearPathName();
	this->myUri.setName("WoshShopWindow");

	WoshShopWindow::instance = this;
	GuiUtilities::setShowWidgetMethod( &showWidget_WoshShopWindow );
 }

WoshShopWindow::~WoshShopWindow() {
	writeSettings();

	this->trayIcon->hide();
	delete this->trayIcon; this->trayIcon = NULL;

	delete this->windowMapper; this->windowMapper = NULL;

	if ( this->formScreenshoter != NULL )
		delete this->formScreenshoter; this->formScreenshoter = NULL;
	if ( this->formConfiguration != NULL )
		delete this->formConfiguration; this->formConfiguration = NULL;

	delete this->m_ui; this->m_ui = NULL;

	WoshShopWindow::instance = NULL;
 }

void WoshShopWindow::init() {
	BusGui.setMessageHandler(this);
	WRESULT bus_gui_connected = BusGui.connect( _Bus_Gui );
	(void)bus_gui_connected;

	setDockOptions( QMainWindow::AnimatedDocks );

	// setup and connect menus
	createMenus();
	// setup tray icon stuff
	createTrayIcon();
	// setup status bar fields
	configureStatusBar();

	refreshInfo();
	readSettings();
 }

void WoshShopWindow::quitWosh() {
	QApplication::quit();
 }

//////////////////////////////////////////////////////////////////////////////////////////////// CONSTRUCTORS
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

void WoshShopWindow::refreshInfo() {
	if ( GuiSession::getInstance().getCurrentKernel() == WoshKernel::getKernelName() ) {
		setWindowTitle( QString("%1 v%2/%3.%4  - OpenSmartHome.com").arg(_APPLICATION_WOSH_WORKSHOP_NAME)
							.arg(_APPLICATION_WOSH_WORKSHOP_VERSION).arg(_WOSH_VER_MAJOR).arg(_WOSH_VER_MINOR) );
		Log(LOG_INFO, ":changeCurrentKernelUser() : Switching to Local Kernel [%s] as %s..", GuiSession::getInstance().getCurrentKernel().c_str(), GuiSession::getInstance().getUsername().c_str() );
	 }
	else {
		setWindowTitle( QString("%1@%2 - %3 v%4/%5.%6")
							.arg(GuiSession::getInstance().getUsername().c_str()).arg(GuiSession::getInstance().getCurrentKernel().c_str()).arg(_APPLICATION_WOSH_WORKSHOP_NAME)
							.arg(_APPLICATION_WOSH_WORKSHOP_VERSION).arg(_WOSH_VER_MAJOR).arg(_WOSH_VER_MINOR) );
		Log(LOG_INFO, ":changeCurrentKernelUser() : Switching to [%s] as %s..", GuiSession::getInstance().getCurrentKernel().c_str(), GuiSession::getInstance().getUsername().c_str() );
	 }
	this->statusBar()->showMessage(tr("Hi %1, Welcome to %2 version %3").arg(GuiSession::getInstance().getUsername().c_str())
																		.arg(_APPLICATION_WOSH_WORKSHOP_NAME)
																		.arg(_APPLICATION_WOSH_WORKSHOP_VERSION), 5000);
	updateDynamicMenus();
	updateStatusBar();
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////// WORKSPACE

void WoshShopWindow::create_GUI( const std::string& name, const std::string& type, const URI& uri, const QStringList& interfaces ) {
	Log(LOG_VERBOSE, ":create_GUI() : GUI for %s [%s]#%i {%s}", name.c_str(), type.c_str(), interfaces.size(), uri.toString().c_str() );
	IWidget* guiWidget = GuiUtilities::create_GUI( name, type, uri, interfaces );
	if ( guiWidget == NULL ) {
		QMessageBox::information(this, this->windowTitle(), QString("Sorry, Can't allocate GUI for '%1' [%2]").arg(type.c_str()).arg(interfaces.join(";")) );
		return;
	 }
	QWidget* qWidget = guiWidget->asQWidget();
	if ( qWidget == NULL )
		return;
	QMdiSubWindow* subWin = this->m_ui->mdiArea->addSubWindow(qWidget);
	subWin->setWindowIcon(qWidget->windowIcon());
	subWin->show();
//	QMenu* m = subWin->systemMenu() ;
//	qWidget->show();
 }

void WoshShopWindow::create_GADGET( const std::string& name, const std::string& type, const URI& uri ) {
	Log(LOG_VERBOSE, ":create_GADGET() : GADGET for %s [%s] {%s}", name.c_str(), type.c_str(), uri.toString().c_str() );
	KioskGadget* kioskWidget = NULL; //this->gadgetAllocator->createObject( type );
	if ( kioskWidget == NULL ) {
		QMessageBox::critical(this, this->windowTitle(), tr("Sorry, Can't allocate GADGET for '%1' [%2]").arg(type.c_str()).arg(name.c_str()) );
		return;
	 }
	kioskWidget->setTargetURI(uri);
	kioskWidget->refreshAll();
	QWidget* widget = kioskWidget->asQWidget();
	if ( widget == NULL )
		return;
	widget->setWindowIcon( GuiUtilities::createIconFor(type) );
	add2DockBar( widget, Qt::RightDockWidgetArea );
 }

void WoshShopWindow::add2DockBar( QWidget* widget, Qt::DockWidgetArea area ) {
	if ( widget == NULL ) return;
	QDockWidget* dock = new QDockWidget(widget->windowTitle(), this);
	dock->setWidget(widget);
	addDockWidget(area, dock);
	this->m_ui->menu_Gadgets->addAction(dock->toggleViewAction());
	widget->show();
 }

/////////////////////////////////////////////////////////////////////////////////////////////////// WORKSPACE
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////// MENU HANLDERS

void WoshShopWindow::menu_StaticItem_triggered( QAction* action ) {
	if ( action == NULL ) return;
	// ---------------------------------------------------------------------------
	// WOSH
	else if ( action == this->m_ui->actionWOSH_ReLogas ) {
		DialogLogin* dSuser = new DialogLogin(this);
		if ( dSuser->exec() == QDialog::Accepted ) {
			GuiSession::getInstance().setUsernameLogged( dSuser->getUserName() );
			GuiSession::getInstance().setCredentials( dSuser->getSecurityTokenProvider()->clone() );
		 }
		dSuser->deleteLater();
		refreshInfo();
	 }
//	else if ( action == this->m_ui->actionWOSH_Import ) {
//		DialogLoadBundle* dLb = new DialogLoadBundle(this);
//		this->m_ui->mdiArea->addSubWindow(dLb);
//		dLb->show();
//	 }
	else if ( action == this->m_ui->actionWOSH_Browser ) {
		if ( this->formWoshBrowser == NULL ) {
			this->formWoshBrowser = new WidgetWoshBrowser();
			connect(this->formWoshBrowser, SIGNAL(request_create_GUI(const string&,const string&,const URI&,const QStringList&)),
					this, SLOT(create_GUI(const string&,const string&,const URI&,const QStringList&)) );
		 }
		this->formWoshBrowser->refreshAll();
		this->formWoshBrowser->show();
		///@todo QMdiSubWindow* subWin = this->m_ui->mdiArea->addSubWindow(this->formWoshBrowser);
		//subWin->show();
	 }
	else if ( action == this->m_ui->actionWOSH_LogViewer ) {
		if ( this->formLogViewer == NULL ) {
			this->formLogViewer = new FormLogViewer();
			add2DockBar( this->formLogViewer, Qt::BottomDockWidgetArea );
		 }
		this->formLogViewer->show();
		///@todo QMdiSubWindow* subWin = this->m_ui->mdiArea->addSubWindow(this->formLogViewer);
		///@todo subWin->show();
	 }
	else if ( action == this->m_ui->actionWOSH_Terminal ) {
		FormConsole* cF = new FormConsole(this);
		this->m_ui->mdiArea->addSubWindow(cF);
		cF->show();
	 }
	else if ( action == this->m_ui->actionWOSH_Quit ) {
		quitWosh();
	 }
	// ---------------------------------------------------------------------------
	// Bundles
	else if ( action == this->m_ui->actionBundles_CreateGUI ) {
		DialogCreateGui* dCgui = new DialogCreateGui(this);
		dCgui->init();
		std::vector<std::string> temp;
//		this->guiAllocator->getSupportedObjects(temp);
//		dCgui->setTypes(temp);
		if ( dCgui->exec() == QDialog::Accepted ) {
			create_GUI(dCgui->getName(), dCgui->getType(), dCgui->getTargetURI(), dCgui->getInterfaces() );
		 }
		dCgui->deleteLater();
	 }
	// ---------------------------------------------------------------------------
	// Network
	else if ( action == this->m_ui->actionNetwork_Refresh ) {
		this->m_ui->menuNetwork_Hosts->refreshAll();
		this->m_ui->menuNetwork_Protocols->refreshAll();
		this->m_ui->menuNetwork_Channels->refreshAll();
	 }
//	else if ( action == this->m_ui->actionNetwork_Listen ) {
//		QMessageBox::warning(this, this->windowTitle(), tr("TODO") );
//	 }
//	else if ( action == this->m_ui->actionNetwork_Connect ) {
//		QMessageBox::warning(this, this->windowTitle(), tr("TODO") );
//	 }
	// ---------------------------------------------------------------------------
	// Tools
	else if ( action == this->m_ui->actionTools_BusViewer ) {
		FormBusViewer* bV = new FormBusViewer(this);
		add2DockBar( bV, Qt::BottomDockWidgetArea );
		//this->m_ui->mdiArea->addSubWindow(bV);
		//bV->show();
	 }
	else if ( action == this->m_ui->actionTools_PropertiesEditor ) {
		WidgetPropertiesEditor* wpE = new WidgetPropertiesEditor(this);
		this->m_ui->mdiArea->addSubWindow(wpE);
		wpE->show();
	 }
	else if ( action == this->m_ui->actionTools_SaveScreenshot ) {
		if ( this->formScreenshoter == NULL ) {
			this->formScreenshoter = new FormScreenshoter();
			//add2Workspace(this->formScreenshoter);
		 }
		this->formScreenshoter->show();
	 }
	else if ( action == this->m_ui->actionTools_Preferences ) {
		if ( this->formConfiguration == NULL ) {
			this->formConfiguration = new FormConfiguration();
			//add2Workspace(this->formScreenshoter);
		 }
		this->formConfiguration->show();
	 }
	else if ( action == this->m_ui->actionTools_GuiMappings ) {
		DialogGuiMapping* dCgui = new DialogGuiMapping(this);
		dCgui->exec();
		dCgui->deleteLater();
	 }
	// ---------------------------------------------------------------------------
	// Gadgets
	else if ( action == this->m_ui->action_GadgetsNew ) {
		DialogCreateGui* dCgui = new DialogCreateGui(this);
		dCgui->setWindowTitle("Create Gadget..");
		std::vector<std::string> temp;
//		this->gadgetAllocator->getSupportedObjects(temp);
//		dCgui->setTypes(temp);
		if ( dCgui->exec() == QDialog::Accepted ) {
			create_GADGET(dCgui->getName(), dCgui->getType(), dCgui->getTargetURI() );
		 }
		dCgui->deleteLater();
	 }
	// ---------------------------------------------------------------------------
	// HELP menu
	else if ( action == this->m_ui->actionHelp_Documentation ) {
		QDesktopServices::openUrl( QUrl(_WOSH_WEB_DOCS) );
	 }
	else if ( action == this->m_ui->actionHelp_WOSH_Online ) {
		QDesktopServices::openUrl( QUrl(_WOSH_WEB_SITE) );
	 }
	else if ( action == this->m_ui->actionHelp_AlessandroPoloOnline ) {
		QDesktopServices::openUrl( QUrl(_WOSH_CREATOR_WEB) );
	 }
	else if ( action == this->m_ui->actionHelp_OpenSmartHome_com ) {
		QDesktopServices::openUrl( QUrl(_OPEN_SMART_HOME_WEB) );
	 }
	else if ( action == this->m_ui->actionHelp_CheckforUpdates ) {
		///@todo CheckforUpdates
		QMessageBox::warning(this, this->windowTitle(), tr("Feature NOT Implemented yet.") );
	 }
	else if ( action == this->m_ui->actionHelp_DonatePaypal ) {
		QDesktopServices::openUrl( QUrl(_WOSH_DONATE_URL) );
	 }
	else if ( action == this->m_ui->actionHelp_AboutWOSHSHOP ) {
		QMessageBox::information(this, this->windowTitle(), "<h1>" _APPLICATION_WOSH_WORKSHOP_NAME "</h1>"
									"<h3>version " _APPLICATION_WOSH_WORKSHOP_VERSION " - 2010</h3>"
									"<h2>All-in-one Frontend for WOSH Network</h2>"
									"<p>Refer to <a href='http://wosh.sourceforge.net'>http://wosh.sourceforge.net</a>.</p>"
									"<p>An open source software by <a href='mailto:contact@alessandropolo.name'>Alessandro Polo</a>.</p>" );
	 }
	else if ( action == this->m_ui->actionHelp_AboutWOSH ) {
		GuiUtilities::aboutWOSH(this);
	 }
	else if ( action == this->m_ui->actionHelp_AboutQT ) {
		QMessageBox::aboutQt(this);
	 }
	else if ( action == this->m_ui->actionHelp_ShowSplash ) {
		QDialog dialog;
		dialog.setWindowTitle( tr("%1 version %2").arg(_APPLICATION_WOSH_WORKSHOP_NAME).arg(_APPLICATION_WOSH_WORKSHOP_VERSION) );
		dialog.setWindowIcon( this->windowIcon() );
		QPixmap splash(":/wosh.splash.icarus.png");
		QLabel* imageLabel = new QLabel(&dialog);
		imageLabel->setPixmap(splash);
		QVBoxLayout l(&dialog);
		l.addWidget(imageLabel);
		dialog.exec();
	 }
	// ---------------------------------------------------------------------------
	// ---------------------------------------------------------------------------
	else if ( action == this->m_ui->actionWindows_DockCurrent ) {
		///@todo todo
	 }
	
 }

void WoshShopWindow::menu_CreateGUI_triggeredItem( WidgetQMenuItem * actionItem ) { // CHANGE TO REMOTEOBJECT !!
	if ( actionItem == NULL ) return;

	create_GUI( actionItem->getRemoteName(), // CHANGE TO REMOTEOBJECT !!
				actionItem->getRemoteType(),
				actionItem->getRemoteURI(),
				actionItem->getInterfaces() ); // CHANGE TO DATALIST in REMOTEOBJECT !!
 }

void WoshShopWindow::menuWOSH_Kernel_triggeredItem( WidgetQMenuItem * actionItem ) {
	if ( actionItem == NULL ) return;
	URI loc = GuiSession::getInstance().getCurrentLocation();
	loc.setKernelName( actionItem->text().toLatin1().data() );
	GuiSession::getInstance().setCurrentLocation(loc);
	refreshInfo();
 }

/////////////////////////////////////////////////////////////////////////////////////////////// MENU HANLDERS
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////// CREATE/UPDATE MENU

void WoshShopWindow::createMenus() {
	Log(LOG_VERBOSE, ":createMenus() : Setting up.." );

	// MENU WOSH
	connect(this->m_ui->menu_Kernels, SIGNAL( triggeredItem( WidgetQMenuItem* ) ), this, SLOT(menuWOSH_Kernel_triggeredItem( WidgetQMenuItem* )));

	// MENU Modules
	connect(this->m_ui->menu_Modules, SIGNAL( triggeredItem( WidgetQMenuItem* ) ), this, SLOT(menu_CreateGUI_triggeredItem( WidgetQMenuItem* )));
	connect(this->m_ui->menu_Modules, SIGNAL( updated() ), this, SLOT(menu_Modules_update_ToolBar()));

	// MENU Bundles
	connect(this->m_ui->menu_Bundles, SIGNAL( triggeredItem( WidgetQMenuItem* ) ), this, SLOT(menu_CreateGUI_triggeredItem( WidgetQMenuItem* )));

	// MENU Devices
	connect(this->m_ui->menu_Devices, SIGNAL( triggeredItem( WidgetQMenuItem* ) ), this, SLOT(menu_CreateGUI_triggeredItem( WidgetQMenuItem* )));

	// MENU Communication
	connect(this->m_ui->menu_Communication, SIGNAL( triggeredItem( WidgetQMenuItem* ) ), this, SLOT(menu_CreateGUI_triggeredItem( WidgetQMenuItem* )));

	// Static items from MENUS
	connect(this->m_ui->menu_WOSH, SIGNAL( triggered( QAction* ) ), this, SLOT(menu_StaticItem_triggered( QAction* )));
	connect(this->m_ui->menu_Bundles, SIGNAL( triggered( QAction* ) ), this, SLOT(menu_StaticItem_triggered( QAction* )));
	connect(this->m_ui->menu_Devices, SIGNAL( triggered( QAction* ) ), this, SLOT(menu_StaticItem_triggered( QAction* )));
	connect(this->m_ui->menu_Network, SIGNAL( triggered( QAction* ) ), this, SLOT(menu_StaticItem_triggered( QAction* )));
	connect(this->m_ui->menu_Gadgets, SIGNAL( triggered( QAction* ) ), this, SLOT(menu_StaticItem_triggered( QAction* )));
	connect(this->m_ui->menu_Tools, SIGNAL( triggered( QAction* ) ), this, SLOT(menu_StaticItem_triggered( QAction* )));
	connect(this->m_ui->menu_Help, SIGNAL( triggered( QAction* ) ), this, SLOT(menu_StaticItem_triggered( QAction* )));


	// menu Windows - direct mapping with QT functions
//	connect(this->m_ui->actionWindows_Close, SIGNAL(triggered()), this->m_ui->mdiArea, SLOT(closeActiveSubWindow()));
	connect(this->m_ui->actionWindows_CloseAll, SIGNAL(triggered()), this->m_ui->mdiArea, SLOT(closeAllSubWindows()));
	connect(this->m_ui->actionWindows_Tile, SIGNAL(triggered()), this->m_ui->mdiArea, SLOT(tileSubWindows()));
	connect(this->m_ui->actionWindows_Cascade, SIGNAL(triggered()), this->m_ui->mdiArea, SLOT(cascadeSubWindows()));
//	connect(this->m_ui->actionWindows_ArrangeIcons, SIGNAL(triggered()), this->m_ui->mdiArea, SLOT(arrangeIcons()));
	connect(this->m_ui->actionWindows_Previous, SIGNAL(triggered()), this->m_ui->mdiArea, SLOT(activatePreviousSubWindow()));
	connect(this->m_ui->actionWindows_Next, SIGNAL(triggered()),this->m_ui->mdiArea, SLOT(activateNextSubWindow()));
	// updates windows list when required
	connect(this->m_ui->menu_Windows, SIGNAL(aboutToShow()), this, SLOT(updateWindowMenu()));

	this->windowMapper = new QSignalMapper(this);
	connect(this->windowMapper, SIGNAL(mapped(QWidget *)), this->m_ui->mdiArea, SLOT(setActiveSubWindow(QMdiSubWindow *)));
 }

void WoshShopWindow::menu_Modules_update_ToolBar() {
	this->m_ui->toolBarModules->clear();
	for (int i=0; i<this->m_ui->menu_Modules->getActionsDynamic().size(); i++) {
		if ( this->m_ui->menu_Modules->getActionsDynamic().at(i) == NULL ) continue;
		WidgetQMenuItem* item = this->m_ui->menu_Modules->getActionsDynamic().at(i);
		this->m_ui->toolBarModules->addAction( item );
	 }
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

void WoshShopWindow::updateDynamicMenus() {
	Log(LOG_VERBOSE, ":updateDynamicMenus() : Updating Menus [%s]..", GuiSession::getInstance().getCurrentKernel().c_str() );

	this->m_ui->menu_Kernels->getTargetURI().setKernelLocal(); // always map to local kernel!
	this->m_ui->menu_Kernels->getTargetURI().setName("Network");
	this->m_ui->menu_Kernels->setDefaultType(WoshHost::className());
	this->m_ui->menu_Kernels->setForceType(true);
	this->m_ui->menu_Kernels->setRequestMethod(_NetworkManager_METHOD_Hosts_list);
	this->m_ui->menu_Kernels->refreshAll();
	std::string kName = GuiSession::getInstance().getCurrentKernel();
	for (int i=0; i<this->m_ui->menu_Kernels->getActionsDynamic().size(); i++) {
		if ( this->m_ui->menu_Kernels->getActionsDynamic().at(i) == NULL ) continue;
		if (this->m_ui->menu_Kernels->getActionsDynamic().at(i)->getRemoteName() == kName )
			this->m_ui->menu_Kernels->getActionsDynamic().at(i)->setChecked(true);
		else
			this->m_ui->menu_Kernels->getActionsDynamic().at(i)->setChecked(false);
	 }

	this->m_ui->menu_Modules->getTargetURI().setKernelName(GuiSession::getInstance().getCurrentKernel());
	this->m_ui->menu_Modules->getTargetURI().setName("");
	this->m_ui->menu_Modules->setRequestMethod(_METHOD_List);
	this->m_ui->menu_Modules->setDefaultType(WoshModule::className());
	this->m_ui->menu_Modules->refreshAll();

	this->m_ui->menu_Bundles->getTargetURI().setKernelName(GuiSession::getInstance().getCurrentKernel());
	this->m_ui->menu_Bundles->getTargetURI().setName("Bundles");
	this->m_ui->menu_Bundles->refreshAll();

	this->m_ui->menu_Devices->getTargetURI().setKernelName(GuiSession::getInstance().getCurrentKernel());
	this->m_ui->menu_Devices->getTargetURI().setName("Devices");
	this->m_ui->menu_Devices->refreshAll();

	this->m_ui->menu_Communication->getTargetURI().setKernelName(GuiSession::getInstance().getCurrentKernel());
	this->m_ui->menu_Communication->getTargetURI().setName("Communication");
	this->m_ui->menu_Communication->setRequestMethod(_CommunicationManager_METHOD_communicators);
	this->m_ui->menu_Communication->refreshAll();

	this->m_ui->menuNetwork_Protocols->getTargetURI().setKernelName(GuiSession::getInstance().getCurrentKernel());
	this->m_ui->menuNetwork_Protocols->getTargetURI().setName("Network");
	this->m_ui->menuNetwork_Protocols->setRequestMethod(_NetworkManager_METHOD_Protocols_list);
	this->m_ui->menuNetwork_Protocols->refreshAll();

	this->m_ui->menuNetwork_Channels->getTargetURI().setKernelName(GuiSession::getInstance().getCurrentKernel());
	this->m_ui->menuNetwork_Channels->getTargetURI().setName("Network");
	this->m_ui->menuNetwork_Channels->setRequestMethod(_NetworkManager_METHOD_Channels_list);
	this->m_ui->menuNetwork_Channels->refreshAll();

	this->m_ui->menuNetwork_Hosts->getTargetURI().setKernelName(GuiSession::getInstance().getCurrentKernel());
	this->m_ui->menuNetwork_Hosts->getTargetURI().setName("Network");
	this->m_ui->menuNetwork_Hosts->setDefaultType(WoshHost::className());
	this->m_ui->menuNetwork_Hosts->setForceType(true);
	this->m_ui->menuNetwork_Hosts->setRequestMethod(_NetworkManager_METHOD_Hosts_list);
	this->m_ui->menuNetwork_Hosts->refreshAll();
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

void WoshShopWindow::updateWindowMenu() {
	Log(LOG_VERBOSE, ":updateWindowMenu() : Rebuiling menu.." );

	this->m_ui->menu_Windows->clear();
	//this->m_ui->menu_Windows->addAction(this->m_ui->actionWindows_Close);
	this->m_ui->menu_Windows->addAction(this->m_ui->actionWindows_CloseAll);
	this->m_ui->menu_Windows->addSeparator();
	this->m_ui->menu_Windows->addAction(this->m_ui->actionWindows_Tile);
	this->m_ui->menu_Windows->addAction(this->m_ui->actionWindows_Cascade);
	this->m_ui->menu_Windows->addSeparator();
	this->m_ui->menu_Windows->addAction(this->m_ui->actionWindows_ArrangeIcons);
	this->m_ui->menu_Windows->addAction(this->m_ui->actionWindows_Previous);
	this->m_ui->menu_Windows->addAction(this->m_ui->actionWindows_Next);
//	this->m_ui->menu_Windows->addAction(menuOptions->menuAction());
	this->m_ui->menu_Windows->addSeparator();

	QList<QMdiSubWindow*> windows = this->m_ui->mdiArea->subWindowList();
	for (int i = 0; i < windows.size(); ++i) {
		QWidget *child = windows.at(i);
		QString text = child->windowTitle();
		QAction *action  = this->m_ui->menu_Windows->addAction(text);
		action->setCheckable(true);
		action ->setChecked(child == this->m_ui->mdiArea->activeSubWindow() );
		connect(action, SIGNAL(triggered()), this->windowMapper, SLOT(map()));
		this->windowMapper->setMapping(action, child);
	 }
 }

////////////////////////////////////////////////////////////////////////////////////////// CREATE/UPDATE MENU
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////// TRAY ICON METHODS

void WoshShopWindow::createTrayIcon() {
	Log(LOG_VERBOSE, ":createTrayIcon() : Setting up.." );

	this->minimizeAction = new QAction(tr("Mi&nimize"), this);
	connect(this->minimizeAction, SIGNAL(triggered()), this, SLOT(hide()));

	this->maximizeAction = new QAction(tr("Ma&ximize"), this);
	connect(this->maximizeAction, SIGNAL(triggered()), this, SLOT(showMaximized()));

	this->restoreAction = new QAction(tr("&Restore"), this);
	connect(this->restoreAction, SIGNAL(triggered()), this, SLOT(showNormal()));

	this->trayIconMenu = new QMenu(this);
	this->trayIconMenu->addAction(minimizeAction);
	this->trayIconMenu->addAction(maximizeAction);
	this->trayIconMenu->addAction(restoreAction);
	this->trayIconMenu->addSeparator();
	this->trayIconMenu->addAction(this->m_ui->actionWOSH_Quit);

	this->trayIcon = new QSystemTrayIcon(this);
	this->trayIcon->setContextMenu(this->trayIconMenu);
	this->trayIcon->setIcon(this->windowIcon());
	this->trayIcon->setToolTip(_APPLICATION_WOSH_WORKSHOP_NAME);
//	connect(this->trayIcon, SIGNAL(messageClicked()), this, SLOT(messageClicked()));
//	connect(this->trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
	this->trayIcon->show();
 }

void WoshShopWindow::configureStatusBar() {
	Log(LOG_VERBOSE, ":configureStatusBar() : Setting up.." );

	this->statusUserAtKernelLbl = new QLabel(this->statusBar());
//	this->statusUserAtKernelLbl->setFrameShape(QFrame::StyledPanel);

	this->statusConnections = new QLabel(this->statusBar());

	QLabel* statusEmpty = new QLabel(this->statusBar());
//	statusEmpty->setFrameShape(QFrame::NoFrame);
//	statusEmpty->setFrameShadow(QFrame::Plain);
//	statusEmpty->setLineWidth(0);

	this->statusBar()->addWidget(statusEmpty, 1);
	this->statusBar()->addWidget(this->statusUserAtKernelLbl, 0);

	updateStatusBar();
 }

void WoshShopWindow::updateStatusBar() {
	this->statusUserAtKernelLbl->setText( QString("%1@%2").arg(GuiSession::getInstance().getUsername().c_str()).arg(GuiSession::getInstance().getCurrentKernel().c_str()) );
 }

void WoshShopWindow::showMessage( const QString& title, const QString& message, long timeout, QSystemTrayIcon::MessageIcon icon ) {
	this->statusBar()->showMessage(tr("%1: %2").arg(title).arg(message), timeout);

	if ( this->trayIcon == NULL )
		return;
	this->trayIcon->showMessage(title, message, icon, timeout);
 }

/////////////////////////////////////////////////////////////////////////////////////////// TRAY ICON METHODS
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////// SETTINGS

void WoshShopWindow::readSettings() {
	Log(LOG_INFO, ":readSettings() : Reading.." );
	QSettings settings("OpenSmartHome.com", _APPLICATION_WOSH_WORKSHOP_NAME);

	int winstate = settings.value("state", (int)Qt::WindowActive).toInt();
	QPoint pos = settings.value("pos", QPoint(50, 50)).toPoint();
	move(pos);
	QSize size = settings.value("size", QSize(800, 600)).toSize();
	resize(size);
	this->setWindowState( (Qt::WindowState)winstate );

	//QString language = settings.value("language", QLocale::system().name() ).toString();
	//loadLanguage(language);

	QString styleName = settings.value("style", "Plastique").toString();
	qApp->setStyle(styleName);

	QString styleSheet = settings.value("styleSheet", "Coffee").toString();
	loadStyleSheet(styleSheet);

	QByteArray winState = settings.value("winState").toByteArray();
	restoreState(winState);
 }

void WoshShopWindow::writeSettings() {
	Log(LOG_INFO, ":writeSettings() : Writing.." );
	QSettings settings("OpenSmartHome.com", _APPLICATION_WOSH_WORKSHOP_NAME);

	settings.setValue("state", (int)this->windowState() );
	if ( this->windowState() != Qt::WindowMaximized && this->windowState() != Qt::WindowFullScreen ) {
		settings.setValue("pos", pos());
		settings.setValue("size", size());
	 }

	settings.setValue("style", qApp->style()->objectName() );
	settings.setValue("styleSheet", qApp->styleSheet() );

	QByteArray winState = saveState(1);
	settings.setValue("winState", winState );

//type|uri

 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

void WoshShopWindow::loadStyleSheet( const QString& sheetName ){
	Log(LOG_INFO, ":loadStyleSheet(%s) : Loading StyleSheet..",sheetName.toLatin1().data() );

	QFile file(":/qss/" + sheetName.toLower() + ".qss");
	file.open(QFile::ReadOnly);
	QString styleSheet = QLatin1String(file.readAll());
	qApp->setStyleSheet(styleSheet);
}

void WoshShopWindow::loadLanguage(const QString& language) {
	if ( language.size() == 0 ) return;
	Log(LOG_INFO, ":loadLanguage(%s) : Loading Translator..",language.toLatin1().data() );

	QTranslator* qtTranslator = new QTranslator();
	QString trQt = "qt_" + language;
	bool loadedQt = qtTranslator->load(trQt, QLibraryInfo::location(QLibraryInfo::TranslationsPath));
	if ( loadedQt )
		qApp->installTranslator(qtTranslator);
//	else
//		QMessageBox::critical(this, this->windowTitle(), QString("Error occurred while loading Translation file [%1].").arg(trQt) );

	QTranslator* woshWidgetTranslator = new QTranslator();
	QString trWw = ":/translations/widgets."+language+".qm";
	bool loadedWw = woshWidgetTranslator->load( trWw );
	if ( loadedWw )
		qApp->installTranslator(woshWidgetTranslator);
	else
		QMessageBox::critical(this, this->windowTitle(), QString("Error occurred while loading Translation file [%1].").arg(trWw) );

	QTranslator* myappTranslator = new QTranslator();
	QString trMy = ":/translations/"+language+".qm";
	bool loadedMy = myappTranslator->load( trMy );
	if ( loadedMy )
		qApp->installTranslator(myappTranslator);
	else
		QMessageBox::critical(this, this->windowTitle(), QString("Error occurred while loading Translation file [%1].").arg(trMy) );
 }

//////////////////////////////////////////////////////////////////////////////////////////////////// SETTINGS
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

QMdiArea* WoshShopWindow::getDocumentArea() { return this->m_ui->mdiArea; }

void WoshShopWindow::changeEvent(QEvent *e) {
	QMainWindow::changeEvent(e);
	switch (e->type()) {
		case QEvent::LanguageChange:
			m_ui->retranslateUi(this);
			refreshInfo(); // refresh title
			break;
		default:
			break;
	 }
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

void WoshShopWindow::busMessage( const Message& message, const Bus* )
 {
	if ( message.isEmpty() ) return;
	if ( message.getContent()->isFact() ) {
		const wosh::Fact* fact = message.getContent()->asFact();
		if ( message.getSource().isKernelLocal() && message.getSource().getName() == "Network"
			&& fact->getEvent() == _WoshHost_EVENT_ListChanged ) {
				this->m_ui->menu_Kernels->refreshAll();
		 }
	 }
	else if ( message.getContent()->isResponse() ) {
		const wosh::Response* response = message.getContent()->asResponse();
		if ( !response->hasData() )
			return;
		if ( !message.getSource().isKernelLocal() || message.getSource().getName() != "Network" )
			return;
		if ( response->getMethod() == _METHOD_GetProperties ) {
			if ( !response->getData()->isKindOf<Table>() )
				return;
			//const wosh::Table* propTable = response->getData()->as<Table>();
		 }
	 }

		//this->statusConnections->setText("X [Y]");
		//this->statusConnections->setToolTip("X Connections [Y Neighbours]");
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

  }; // namespace application
}; // namespace wosh
